package com.zxw.ui;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Spinner;
import android.widget.Toast;

import com.sevenheaven.segmentcontrol.SegmentControl;
import com.zxw.R;
import com.zxw.cmd.CmdEntry;
import com.zxw.toolkit.UIHandler;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import static android.widget.Toast.LENGTH_LONG;
import static com.zxw.cmd.CmdDefine.CMD_RESULT_TIMEOUT;

public class StdFragment extends BaseFragment implements View.OnClickListener {

    private static final String TAG = StdFragment.class.getSimpleName();

    // --------------------------------------------------------------------
    // MODE
    public static final int MODE_STD = 0;
    public static final int MODE_SYN = 1;
    public static final int MODE_FLOW = 2;
    public static final int MODE_RRFB = 3;
    public static final int MODE_IOT = 4;
    public static final int MODE_GET = 5;
    @IntDef({MODE_STD, MODE_SYN, MODE_FLOW, MODE_RRFB, MODE_IOT, MODE_GET})
    @Retention(RetentionPolicy.SOURCE)
    public @interface MODE_VALUES {}

    // --------------------------------------------------------------------
    // BATTERY
    public static final int BATTER_LAND = 0;
    public static final int BATTER_LION = 1;
    @IntDef({BATTER_LAND, BATTER_LION})
    @Retention(RetentionPolicy.SOURCE)
    public @interface BATTERY_VALUES {}

    // --------------------------------------------------------------------
    // TRIGGER
    public static final int TRIGGER_VALUE_DRY = 0;
    public static final int TRIGGER_VALUE_HIGH = 1;
    public static final int TRIGGER_VALUE_LOW = 2;
    @IntDef({TRIGGER_VALUE_DRY, TRIGGER_VALUE_HIGH, TRIGGER_VALUE_LOW})
    @Retention(RetentionPolicy.SOURCE)
    public @interface TRIGGER_VALUES {}

    // --------------------------------------------------------------------
    // TRIGGER
    public static final int TRIGGER_TIME_8S = 0;
    public static final int TRIGGER_TIME_12S = 1;
    public static final int TRIGGER_TIME_16S = 2;
    public static final int TRIGGER_TIME_20S = 3;
    public static final int TRIGGER_TIME_24S = 4;
    public static final int TRIGGER_TIME_28S = 5;
    public static final int TRIGGER_TIME_32S = 6;
    public static final int TRIGGER_TIME_1MIN = 7;
    public static final int TRIGGER_TIME_2MIN = 8;
    public static final int TRIGGER_TIME_3MIN = 9;
    public static final int TRIGGER_TIME_4MIN = 10;
    public static final int TRIGGER_TIME_5MIN = 11;
    public static final int TRIGGER_TIME_10MIN = 12;
    public static final int TRIGGER_TIME_15MIN = 13;
    public static final int TRIGGER_TIME_20MIN = 14;
    public static final int TRIGGER_TIME_30MIN = 15;
    @IntDef({
            TRIGGER_TIME_8S, TRIGGER_TIME_12S, TRIGGER_TIME_16S, TRIGGER_TIME_20S,
            TRIGGER_TIME_24S, TRIGGER_TIME_28S, TRIGGER_TIME_32S,
            TRIGGER_TIME_1MIN, TRIGGER_TIME_2MIN, TRIGGER_TIME_3MIN, TRIGGER_TIME_4MIN,
            TRIGGER_TIME_5MIN, TRIGGER_TIME_10MIN, TRIGGER_TIME_15MIN,
            TRIGGER_TIME_20MIN, TRIGGER_TIME_30MIN
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TRIGGER_TIMES {}

    private LightController lightController1;
    private LightController lightController2;
    private LightController lightController3;
    private Spinner modeSpinner;
    private Spinner batterySpinner;
    private View triggerView;
    private Spinner triggerModeSpinner;
    private Spinner triggerTimeSpinner;
    private View progressView;

    private int stdDuty = 0;
    private View stdDutyLayout;
    private SegmentControl stdDutySegment;

    private int iotDuty = 0;
    private View iotDutyLayout;
    private SegmentControl iotDutySegment;

    private int synDuty = 0;
    private View synDutyLayout;
    private SegmentControl synDutySegment;

    private int flowDuty = 0;
    private View flowDutyLayout;
    private SegmentControl flowDutySegment;

    private long showProgressTime = 0;
    private final Runnable delaySave = this::onSave;
    private final AdapterView.OnItemSelectedListener spinnerListener = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            UIHandler.removeCallbacks(delaySave);
            UIHandler.postDelayed(delaySave, 500);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    };

    public StdFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_std, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initViews();
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    private void initViews() {

        View view = getView();
        if (null == view) {
            Log.e(TAG, "Error find views");
            return;
        }

        View readButton = view.findViewById(R.id.btn_read);
        readButton.setOnClickListener(this);
        readButton.setVisibility(View.GONE);

        View saveButton = view.findViewById(R.id.btn_save);
        saveButton.setOnClickListener(this);

        View resetButton = view.findViewById(R.id.btn_reset);
        resetButton.setOnClickListener(this);
        resetButton.setVisibility(View.GONE);

        LightController.ILightControlDelegate delegate = this::onSave;

        View lightConfigView1 = view.findViewById(R.id.light_config_layout_ch1);
        lightController1 = new LightController(lightConfigView1, delegate);
        lightController1.setTitle(R.string.ch1);

        View lightConfigView2 = view.findViewById(R.id.light_config_layout_ch2);
        lightController2 = new LightController(lightConfigView2, delegate);
        lightController2.setTitle(R.string.ch2);

        View lightConfigView3 = view.findViewById(R.id.light_config_layout_ch3);
        lightController3 = new LightController(lightConfigView3, delegate);
        lightController3.setTitle(R.string.ch3);

        modeSpinner = view.findViewById(R.id.mode_checker);
        batterySpinner = view.findViewById(R.id.battery_checker);

        triggerView = view.findViewById(R.id.trigger_mode_layout);
        triggerModeSpinner = view.findViewById(R.id.trigger_mode_checker);
        triggerTimeSpinner = view.findViewById(R.id.trigger_time_checker);

        progressView = view.findViewById(R.id.progress_layout);

        stdDutyLayout = view.findViewById(R.id.std_duty_layout);
        stdDutySegment = view.findViewById(R.id.segment_control_std_duty);
        iotDutyLayout = view.findViewById(R.id.iot_duty_layout);
        iotDutySegment = view.findViewById(R.id.segment_control_iot_duty);
        synDutyLayout = view.findViewById(R.id.syn_duty_layout);
        synDutySegment = view.findViewById(R.id.segment_control_syn_duty);
        flowDutyLayout = view.findViewById(R.id.flow_duty_layout);
        flowDutySegment = view.findViewById(R.id.segment_control_flow_duty);

        //
        stdDutySegment.setSelectedIndex(stdDuty);
        stdDutySegment.setOnSegmentControlClickListener(index -> {
            stdDuty = index;
            onSave();
        });

        iotDutySegment.setSelectedIndex(iotDuty);
        iotDutySegment.setOnSegmentControlClickListener(index -> {
            iotDuty = index;
            onSave();
        });

        synDutySegment.setSelectedIndex(synDuty);
        synDutySegment.setOnSegmentControlClickListener(index -> {
            synDuty = index;
            onSave();
        });

        flowDutySegment.setSelectedIndex(flowDuty);
        flowDutySegment.setOnSegmentControlClickListener(index -> {
            flowDuty = index;
            onSave();
        });

        modeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                switch (position) {
                    case MODE_STD:{
                        triggerView.setVisibility(View.GONE);
                        stdDutyLayout.setVisibility(View.VISIBLE);
                        iotDutyLayout.setVisibility(View.GONE);
                        synDutyLayout.setVisibility(View.GONE);
                        flowDutyLayout.setVisibility(View.GONE);
                        break;
                    }
                    case MODE_SYN: {
                        triggerView.setVisibility(View.GONE);
                        stdDutyLayout.setVisibility(View.GONE);
                        iotDutyLayout.setVisibility(View.GONE);
                        synDutyLayout.setVisibility(View.VISIBLE);
                        flowDutyLayout.setVisibility(View.GONE);
                        break;
                    }
                    case MODE_FLOW: {
                        triggerView.setVisibility(View.GONE);
                        stdDutyLayout.setVisibility(View.GONE);
                        iotDutyLayout.setVisibility(View.GONE);
                        synDutyLayout.setVisibility(View.GONE);
                        flowDutyLayout.setVisibility(View.VISIBLE);
                        break;
                    }
                    case MODE_RRFB: {
                        triggerView.setVisibility(View.VISIBLE);
                        stdDutyLayout.setVisibility(View.GONE);
                        iotDutyLayout.setVisibility(View.GONE);
                        synDutyLayout.setVisibility(View.GONE);
                        flowDutyLayout.setVisibility(View.GONE);
                        break;
                    }
                    case MODE_IOT: {
                        triggerView.setVisibility(View.VISIBLE);
                        stdDutyLayout.setVisibility(View.GONE);
                        iotDutyLayout.setVisibility(View.VISIBLE);
                        synDutyLayout.setVisibility(View.GONE);
                        flowDutyLayout.setVisibility(View.GONE);
                        break;
                    }
                    case MODE_GET: {
                        UIHandler.postDelayed(StdFragment.this::onGet, 500);
                        return;
                    }
                    default:
                        Log.e(TAG, "no one handle this ---");
                        break;
                }

                CmdEntry entry = new CmdEntry();
                entry.mode = (byte) position;
                readFromPreferences(entry);
                onGetCmdEntry(entry);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        UIHandler.postDelayed(() -> {
            batterySpinner.setOnItemSelectedListener(spinnerListener);
            triggerModeSpinner.setOnItemSelectedListener(spinnerListener);
            triggerTimeSpinner.setOnItemSelectedListener(spinnerListener);
        }, 1000);
    }

    private void showProgress() {
        UIHandler.post(() -> {
            showProgressTime = System.currentTimeMillis();
            if (progressView != null) {
                progressView.setVisibility(View.VISIBLE);
            }
        });
    }

    private void hideProgress() {
        UIHandler.post(() -> {
            long now = System.currentTimeMillis();
            if (now - showProgressTime < 1000) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (progressView != null) {
                progressView.setVisibility(View.GONE);
            }
        });
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.btn_read: {
                onGet();
                break;
            }

            case R.id.btn_save: {
                onSave();
                break;
            }

            case R.id.btn_reset: {
                break;
            }

            default:
                break;
        }
    }

    private void onGet() {

        CmdEntry entrySnd = new CmdEntry();
        entrySnd.mode = MODE_GET;
        if (null != cmdSender) {
            showProgress();
            cmdSender.send(entrySnd, (result, entryRes) -> {
                hideProgress();
                if (result == CMD_RESULT_TIMEOUT || entryRes == null) {
                    UIHandler.post(() -> {
                        if (getContext() != null) {
                            Toast.makeText(getContext(), "get failed !!!", LENGTH_LONG).show();
                        }
                        if (modeSpinner.getSelectedItemPosition() == MODE_GET) {
                            modeSpinner.setSelection(MODE_STD);
                        }
                    });
                    return;
                }
                Log.d(TAG, "get result --- " + result);
                Log.d(TAG, "get data --- " + new String(entryRes.getBytes()));
                onGetCmdEntry(entryRes);
            });
        }
    }

    @SuppressLint("ShowToast")
    private void onSave() {

        CmdEntry entrySnd = new CmdEntry();
        entrySnd.mode = (byte) modeSpinner.getSelectedItemPosition();
        entrySnd.ch1DayLight = (byte) lightController1.getDayLight();
        entrySnd.ch1NightLight = (byte) lightController1.getNightLight();
        entrySnd.ch2DayLight = (byte) lightController2.getDayLight();
        entrySnd.ch2NightLight = (byte) lightController2.getNightLight();
        entrySnd.ch3DayLight = (byte) lightController3.getDayLight();
        entrySnd.ch3NightLight = (byte) lightController3.getNightLight();
        entrySnd.battery = (byte) batterySpinner.getSelectedItemPosition();

        switch (entrySnd.mode) {
            case MODE_STD:
                entrySnd.ch1Duty = (byte) stdDuty;
                entrySnd.ch2Duty = (byte) 0;
                entrySnd.ch3Duty = (byte) 0;
                break;
            case MODE_IOT:
                entrySnd.ch1Duty = (byte) iotDuty;
                entrySnd.ch2Duty = (byte) 0;
                entrySnd.ch3Duty = (byte) 0;
                break;
            case MODE_SYN:
                entrySnd.ch1Duty = (byte) synDuty;
                entrySnd.ch2Duty = (byte) 0;
                entrySnd.ch3Duty = (byte) 0;
                break;
            case MODE_FLOW:
                entrySnd.ch1Duty = (byte) flowDuty;
                entrySnd.ch2Duty = (byte) 0;
                entrySnd.ch3Duty = (byte) 0;
                break;

            case MODE_RRFB:
                entrySnd.ch1Duty = (byte) 0;
                entrySnd.ch2Duty = (byte) 0;
                entrySnd.ch3Duty = (byte) 0;
                break;
            default:
                Log.e(TAG, "no one handle this ---");
                break;
        }

        if (triggerView.getVisibility() == View.VISIBLE) {
            entrySnd.triggerMode = (byte) triggerModeSpinner.getSelectedItemPosition();
            entrySnd.triggerTime = (byte) triggerTimeSpinner.getSelectedItemPosition();
        } else {
            entrySnd.triggerMode = 0;
            entrySnd.triggerTime = 0;
        }

        saveToPreferences(entrySnd);

        if (null != cmdSender) {
            showProgress();
            cmdSender.send(entrySnd, (result, entryRes) -> {
                hideProgress();
                if (result == CMD_RESULT_TIMEOUT || entryRes == null) {
                    UIHandler.post(() -> {
                        if (getContext() != null) {
                            Toast.makeText(getContext(), "save failed !!!", LENGTH_LONG).show();
                        }
                    });
                    return;
                }
                Log.d(TAG, "get result --- " + result);
                Log.d(TAG, "get data --- " + new String(entryRes.getBytes()));
                onGetCmdEntry(entryRes);
            });
        }
    }

    private void saveToPreferences(CmdEntry entrySnd) {
        Activity activity= getActivity();
        if (null == activity) {
            return;
        }
        //步骤1：创建一个SharedPreferences对象
        SharedPreferences sharedPreferences = activity.getSharedPreferences("data", Context.MODE_PRIVATE);

        //步骤2： 实例化SharedPreferences.Editor对象
        SharedPreferences.Editor editor = sharedPreferences.edit();

        //步骤3：将获取过来的值放入文件
        editor.putString("" + entrySnd.mode, entrySnd.getDesString());

        //步骤4：提交
        editor.apply();
    }

    private void readFromPreferences(CmdEntry entry) {
        Activity activity= getActivity();
        if (null == activity) {
            return;
        }

        //步骤1：创建一个SharedPreferences对象
        SharedPreferences sharedPreferences = activity.getSharedPreferences("data", Context.MODE_PRIVATE);

        //步骤2：读取数据
        String desString = sharedPreferences.getString("" + entry.mode, "");
        if (TextUtils.isEmpty(desString)) {
            return;
        }

        //步骤3：填充
        entry.putDesString(desString);
    }

    public void onGetCmdEntry(@NonNull CmdEntry entry) {
        if (MODE_GET == entry.mode) {
            onSave();
            return;
        }
        modeSpinner.setSelection(entry.mode);
        lightController1.setDayLight(entry.ch1DayLight);
        lightController1.setNightLight(entry.ch1NightLight);
        lightController2.setDayLight(entry.ch2DayLight);
        lightController2.setNightLight(entry.ch2NightLight);
        lightController3.setDayLight(entry.ch3DayLight);
        lightController3.setNightLight(entry.ch3NightLight);

        batterySpinner.setOnItemSelectedListener(null);
        triggerModeSpinner.setOnItemSelectedListener(null);
        triggerTimeSpinner.setOnItemSelectedListener(null);

        batterySpinner.setSelection(entry.battery);
        triggerModeSpinner.setSelection(entry.triggerMode);
        triggerTimeSpinner.setSelection(entry.triggerTime);

        UIHandler.postDelayed(() -> {
            batterySpinner.setOnItemSelectedListener(spinnerListener);
            triggerModeSpinner.setOnItemSelectedListener(spinnerListener);
            triggerTimeSpinner.setOnItemSelectedListener(spinnerListener);
        }, 1000);

        if (entry.mode == MODE_IOT) {
            iotDutySegment.setSelectedIndex(entry.ch1Duty);
        } else if (entry.mode == MODE_STD) {
            stdDutySegment.setSelectedIndex(entry.ch1Duty);
        } else if (entry.mode == MODE_SYN) {
            synDutySegment.setSelectedIndex(entry.ch1Duty);
        } else if (entry.mode == MODE_FLOW) {
            flowDutySegment.setSelectedIndex(entry.ch1Duty);
        }
    }
}